#!/usr/bin/python3

import socket
import time
import subprocess
import signal

conf = {
        "interval_time_s": 3
}

int_to_ip = lambda x: '.'.join([str(x//(256**i)%256) for i in range(3,-1,-1)])
ip_to_int = lambda x:sum([256**j*int(i) for j,i in enumerate(x.split('.')[::-1])])

get_tcp4_status_cmd = 'cat /proc/net/tcp'

g_sock_set = set() # set


def user_signal_handler(signum, frame):
    if signum == signal.SIGUSR1:
        print("recv sig: user1")
    elif signum == signal.SIGUSR2:
        print("recv sig: user2")


signal.signal(signal.SIGUSR1, user_signal_handler)
signal.signal(signal.SIGUSR2, user_signal_handler)

def runcmd(command):
    ret = subprocess.run(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding="utf-8",timeout=1)
    #if ret.returncode == 0:
        # print("exec success")
    #else:
    #    print("exec error")
    return ret

def get_timestamp_s():
    return int(time.time())

class Sock:
    def __init__(self, src_ip='', src_port='', dst_ip='', dst_port=''):
        self.src_ip = src_ip
        self.src_port = src_port
        self.dst_ip = dst_ip
        self.dst_port = dst_port

        self.tcp_status = '' 
        self.start_time = 0  # 第一次检测到的时间
        self.delta_time = 0  # 持续时间,正在进行中为-1

    def __eq__(self, other):
        if isinstance(other, Sock):
            return ((self.src_ip == other.src_ip) and (self.src_port == other.src_port) and (self.dst_ip == other.dst_ip) and (self.dst_port == other.dst_port))
        else:
            return False
    def __ne__(self, other):
        return (not self.__eq__(other))
    
    def __hash__(self):
        return hash(self.src_ip) + hash(self.src_port) + hash(self.dst_ip) + hash(self.dst_port)

    def to_string(self):
        end_time = get_timestamp_s()
        self.delta_time = end_time - self.start_time
        return "%s:%s<->%s:%s %s %s %s" %(self.src_ip, self.src_port, self.dst_ip, self.dst_port, self.tcp_status, self.start_time, self.delta_time)

'''
    TCP_ESTABLISHED:1   TCP_SYN_SENT:2
    TCP_SYN_RECV:3      TCP_FIN_WAIT1:4
    TCP_FIN_WAIT2:5     TCP_TIME_WAIT:6
    TCP_CLOSE:7         TCP_CLOSE_WAIT:8
    TCP_LAST_ACL:9      TCP_LISTEN:10
    TCP_CLOSING:11
'''
def get_tcp_status(status):
    if status == 1:
        return 'established'
    elif status == 2:
        return 'syn_sent'
    elif status == 3:
        return 'syn_recv'
    elif status == 4:
        return 'fin_wait1'
    elif status == 5:
        return 'fin_wait2'
    elif status == 6:
        return 'time_wait'
    elif status == 7:
        return 'close'
    elif status == 8:
        return 'close_wait'
    elif status == 9:
        return 'last_ack'
    elif status == 10:
        return 'listen'
    elif status == 11:
        return 'closing'

def create_sock(src_ip_port, dst_ip_port, status):
    src_ip,src_port = (src_ip_port.split(':'))
    dst_ip,dst_port = (dst_ip_port.split(':'))

    src_ip = int_to_ip(socket.htonl(int(src_ip, 16)))
    src_port = str(int(src_port, 16))
    dst_ip = int_to_ip(socket.htonl(int(dst_ip, 16)))
    dst_port = str(int(dst_port, 16))
    # print(src_ip, src_port, dst_ip, dst_port)
    s = Sock()
    s.src_ip = src_ip
    s.src_port = src_port
    s.dst_ip = dst_ip
    s.dst_port = dst_port
    s.tcp_status = get_tcp_status(int(status, 16))
    s.start_time = get_timestamp_s()
    s.delta_time = -1
    return s

def process_once():
    ret = runcmd(get_tcp4_status_cmd)
    if ret.returncode != 0:
        exit(0)

    lines = ret.stdout.split('\n')
    lines = lines[1:]
    for line in lines:
        line = line.strip()
        if line == '':
            continue
        line_arr = line.strip().split(' ')
        s = create_sock(line_arr[1], line_arr[2], line_arr[3])
        g_sock_set.add(s)

    for s in g_sock_set:
        print(s.to_string())

if __name__ == '__main__':
    while True:
        print("========================================")
        process_once()
        time.sleep(conf["interval_time_s"])
